package com.jse.jakarta;

import java.io.IOException;
import java.net.HttpCookie;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.jse.Fs;
import com.jse.Io;
import com.jse.Jse;
import com.jse.Strings;
import com.jse.api.Oss;
import com.jse.json.Json;
import com.jse.json.JsonObject;
import com.jse.json.XML;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.Part;

public class Tbl implements Map<String,Object> {
	
	private String method;
	private String path;
	private String suffix;
	private Map<String,HttpCookie> cookies;
	private String serverName;
	
	private JsonObject tbl=new JsonObject();
	HttpServletRequest req;
	public Tbl(HttpServletRequest req) {
		this.req=req;
		method=req.getMethod();
		path=Strings.def(req.getServletPath(),req.getPathInfo());
		int suffixindex=path.lastIndexOf(".");
		suffix=suffixindex==-1?path:path.substring(suffixindex+1);
		serverName=req.getServerName();
		try{parseTbl(req);} catch (IOException e) {e.printStackTrace();}
	}

	@Override public int size() {return tbl.size();}
	@Override public boolean isEmpty() {return tbl.isEmpty();}
	@Override public boolean containsKey(Object key) {return tbl.containsKey(key);}
	@Override public boolean containsValue(Object value) {return tbl.containsValue(value);}
	@Override public Object get(Object key) {return tbl.get(key);}
	@Override public Object put(String key, Object value) {return tbl.put(key, value);}
	@Override public Object remove(Object key) {return tbl.remove(key);}
	@Override public void putAll(Map<? extends String, ? extends Object> m) {tbl.putAll(m);}
	@Override public void clear() {tbl.clear();}
	@Override public Set<String> keySet() {return tbl.keySet();}
	@Override public Collection<Object> values() {return tbl.values();}
	@Override public Set<Entry<String, Object>> entrySet() {return tbl.entrySet();}
	@Override public String toString() {return Json.toJson(this);}

	private void parseTbl(HttpServletRequest req) throws IOException {
		if("GET".equals(method)) {
	        req.getParameterMap().forEach((k,v)->{
	        	tbl.add(k,v!=null?(v.length==1?v[0]:Arrays.asList(v)):v);
	        });
		}else if("POST".equals(method)) {
        	String reqcontentType=req.getContentType();
        	if(reqcontentType==null) {//没有body none
        	}else if(reqcontentType.startsWith("application/x-www-form-urlencoded")) {
        		tbl.putAll(new JsonObject(Io.readString(req.getReader())));
            }else if(reqcontentType.startsWith("application/json")) {
            	tbl.putAll(Json.jsonObject(Io.readString(req.getReader())));
            }else if(reqcontentType.startsWith("application/xml")) {
            	tbl.putAll(XML.toJSONObject(Io.readString(req.getReader())));
            }else if(reqcontentType.startsWith("multipart/form-data")) {//上传
            	try {
					var d=LocalDateTime.now();
					Map<String,String> ups=new HashMap<>();
					for(Part part:req.getParts()) {
						if(part.getSubmittedFileName()!= null&&part.getSize()>0) {
							tbl.put(part.getName(),part);
							if(path.equals("/jse/up")||Jse.webuploadauto) {
								ups.put(part.getName(),null);
							}
						}else {
							if(part.getName().charAt(0)=='_'&&part.getName().endsWith("_")) {
								ups.put(part.getName(),req.getParameter(part.getName()));
							}else {
								tbl.put(part.getName(),req.getParameter(part.getName()));
							}
						}
					}
					for (String key : ups.keySet()) {
						if(key.charAt(0)!='_'&&!key.endsWith("_")) {//非_开头和结尾
							Part part=req.getPart(key);
							String filePath=ups.get(key);
							if(ups.containsKey("_"+key+"_")) {
								filePath=ups.get("_"+key+"_");
							}else if(ups.containsKey("_f_")) {
								filePath=ups.get("_f_");
							}else if(ups.containsKey("_path_")) {
								filePath=ups.get("_path_")+part.getSubmittedFileName();
							}else {
								String suffix0=Strings.def(Fs.suffix(part.getSubmittedFileName()),"txt");
								filePath="/upload/"+Jse.name+"/"+
							d.getYear()+"/"+d.getMonth()+"/"+d.getDayOfMonth()+"/"+System.nanoTime()+"."+suffix0;//自动路径
							}
							tbl.put(key,filePath);
							String uploadpath=Jse.conf.get("web.upload",Jse.webapps());
							String abspath=uploadpath+filePath;
							Fs.mkdirs(abspath);
							part.write(abspath);//把文件写到指定路径
							if(Jse.conf.containsKey("ali.oss.bucket")) {
								if(filePath.charAt(0)=='/')filePath=filePath.substring(1);
								String oss=Oss.upload(Map.of("path",filePath,"file",abspath));
								System.out.println("oss up file "+oss);
								Jse.conf.add("tempfile",abspath);
								tbl.put(key,oss);
								Fs.delete(Path.of(abspath));
							}
							part.delete();//删除文件项的基础存储，包括删除任何关联的临时磁盘文件。
						}
					}
				} catch (IOException|ServletException e) {e.printStackTrace();
				}
            }else {
            	tbl.put("body",Io.readString(req.getReader()));
            }
        }
	}
	public String getPath() {return path;}
	public String getSuffix() {return suffix;}
	public JsonObject getTbl() {return tbl;}
	public String getServerName() {return serverName;}
}
